package com.christina.engine.observer.impl;

import com.christina.engine.observer.ProcessingEvent;
import com.christina.engine.observer.ProcessingEventListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.EnumSet;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 指标收集监听器
 * 负责收集系统性能和业务指标
 * 
 * @author Christina
 */
@Slf4j
@Component
public class MetricsCollectionListener implements ProcessingEventListener {
    
    private static final String LISTENER_NAME = "MetricsCollectionListener";
    
    // 支持的事件类型
    private static final EnumSet<ProcessingEvent.EventType> SUPPORTED_EVENTS = EnumSet.of(
            ProcessingEvent.EventType.REQUEST_RECEIVED,
            ProcessingEvent.EventType.REQUEST_PROCESSED,
            ProcessingEvent.EventType.REQUEST_COMPLETED,
            ProcessingEvent.EventType.REQUEST_FAILED,
            ProcessingEvent.EventType.SERVICE_EXECUTION_STARTED,
            ProcessingEvent.EventType.SERVICE_EXECUTION_COMPLETED,
            ProcessingEvent.EventType.SERVICE_EXECUTION_FAILED,
            ProcessingEvent.EventType.RESPONSE_GENERATED,
            ProcessingEvent.EventType.PERFORMANCE_METRIC,
            ProcessingEvent.EventType.ERROR_OCCURRED
    );
    
    // 指标存储
    private final Map<String, AtomicLong> counters = new ConcurrentHashMap<>();
    private final Map<String, AtomicLong> timers = new ConcurrentHashMap<>();
    private final Map<String, Double> gauges = new ConcurrentHashMap<>();
    
    @Override
    public void onEvent(ProcessingEvent event) {
        try {
            switch (event.getEventType()) {
                case REQUEST_RECEIVED:
                    handleRequestReceived(event);
                    break;
                case REQUEST_PROCESSED:
                    handleRequestProcessed(event);
                    break;
                case REQUEST_COMPLETED:
                    handleRequestCompleted(event);
                    break;
                case REQUEST_FAILED:
                    handleRequestFailed(event);
                    break;
                case SERVICE_EXECUTION_STARTED:
                    handleServiceExecutionStarted(event);
                    break;
                case SERVICE_EXECUTION_COMPLETED:
                    handleServiceExecutionCompleted(event);
                    break;
                case SERVICE_EXECUTION_FAILED:
                    handleServiceExecutionFailed(event);
                    break;
                case RESPONSE_GENERATED:
                    handleResponseGenerated(event);
                    break;
                case PERFORMANCE_METRIC:
                    handlePerformanceMetric(event);
                    break;
                case ERROR_OCCURRED:
                    handleErrorOccurred(event);
                    break;
                default:
                    log.debug("Unhandled event type: {}", event.getEventType());
            }
        } catch (Exception e) {
            log.error("Error processing metrics for event: {}", event.getEventId(), e);
        }
    }
    
    /**
     * 处理请求接收事件
     */
    private void handleRequestReceived(ProcessingEvent event) {
        incrementCounter("requests.received.total");
        incrementCounter("requests.received.by_source." + event.getSource());
        
        if (event.getUserId() != null) {
            incrementCounter("requests.received.by_user");
        }
        
        log.debug("Recorded request received metric for session: {}", event.getSessionId());
    }
    
    /**
     * 处理请求处理事件
     */
    private void handleRequestProcessed(ProcessingEvent event) {
        incrementCounter("requests.processed.total");
        
        // 记录处理时间
        if (event.getEventData() != null) {
            Object processingTime = event.getEventData().get("processingTime");
            if (processingTime instanceof Number) {
                recordTimer("requests.processing_time", ((Number) processingTime).longValue());
            }
        }
    }
    
    /**
     * 处理请求完成事件
     */
    private void handleRequestCompleted(ProcessingEvent event) {
        incrementCounter("requests.completed.total");
        incrementCounter("requests.completed.by_source." + event.getSource());
        
        // 记录总响应时间
        if (event.getEventData() != null) {
            Object responseTime = event.getEventData().get("responseTime");
            if (responseTime instanceof Number) {
                recordTimer("requests.response_time", ((Number) responseTime).longValue());
            }
        }
    }
    
    /**
     * 处理请求失败事件
     */
    private void handleRequestFailed(ProcessingEvent event) {
        incrementCounter("requests.failed.total");
        incrementCounter("requests.failed.by_source." + event.getSource());
        
        // 按错误类型分类
        if (event.getEventData() != null) {
            Object errorType = event.getEventData().get("errorType");
            if (errorType != null) {
                incrementCounter("requests.failed.by_error_type." + errorType);
            }
        }
    }
    
    /**
     * 处理服务执行开始事件
     */
    private void handleServiceExecutionStarted(ProcessingEvent event) {
        incrementCounter("service.executions.started.total");
        
        if (event.getEventData() != null) {
            Object serviceName = event.getEventData().get("serviceName");
            if (serviceName != null) {
                incrementCounter("service.executions.started.by_service." + serviceName);
            }
        }
    }
    
    /**
     * 处理服务执行完成事件
     */
    private void handleServiceExecutionCompleted(ProcessingEvent event) {
        incrementCounter("service.executions.completed.total");
        
        if (event.getEventData() != null) {
            Object serviceName = event.getEventData().get("serviceName");
            Object executionTime = event.getEventData().get("executionTime");
            
            if (serviceName != null) {
                incrementCounter("service.executions.completed.by_service." + serviceName);
                
                if (executionTime instanceof Number) {
                    recordTimer("service.execution_time.by_service." + serviceName, 
                              ((Number) executionTime).longValue());
                }
            }
        }
    }
    
    /**
     * 处理服务执行失败事件
     */
    private void handleServiceExecutionFailed(ProcessingEvent event) {
        incrementCounter("service.executions.failed.total");
        
        if (event.getEventData() != null) {
            Object serviceName = event.getEventData().get("serviceName");
            if (serviceName != null) {
                incrementCounter("service.executions.failed.by_service." + serviceName);
            }
        }
    }
    
    /**
     * 处理响应生成事件
     */
    private void handleResponseGenerated(ProcessingEvent event) {
        incrementCounter("responses.generated.total");
        
        if (event.getEventData() != null) {
            Object responseLength = event.getEventData().get("responseLength");
            if (responseLength instanceof Number) {
                recordGauge("responses.average_length", ((Number) responseLength).doubleValue());
            }
        }
    }
    
    /**
     * 处理性能指标事件
     */
    private void handlePerformanceMetric(ProcessingEvent event) {
        if (event.getEventData() != null) {
            Object metricName = event.getEventData().get("metricName");
            Object metricValue = event.getEventData().get("metricValue");
            
            if (metricName != null && metricValue instanceof Number) {
                String fullMetricName = "performance." + metricName;
                recordGauge(fullMetricName, ((Number) metricValue).doubleValue());
            }
        }
    }
    
    /**
     * 处理错误发生事件
     */
    private void handleErrorOccurred(ProcessingEvent event) {
        incrementCounter("errors.total");
        incrementCounter("errors.by_source." + event.getSource());
        
        if (event.getEventData() != null) {
            Object errorType = event.getEventData().get("errorType");
            if (errorType != null) {
                incrementCounter("errors.by_type." + errorType);
            }
        }
    }
    
    /**
     * 增加计数器
     */
    private void incrementCounter(String name) {
        counters.computeIfAbsent(name, k -> new AtomicLong(0)).incrementAndGet();
    }
    
    /**
     * 记录计时器
     */
    private void recordTimer(String name, long value) {
        timers.computeIfAbsent(name, k -> new AtomicLong(0)).addAndGet(value);
    }
    
    /**
     * 记录仪表盘指标
     */
    private void recordGauge(String name, double value) {
        gauges.put(name, value);
    }
    
    /**
     * 获取计数器值
     */
    public long getCounterValue(String name) {
        AtomicLong counter = counters.get(name);
        return counter != null ? counter.get() : 0;
    }
    
    /**
     * 获取计时器值
     */
    public long getTimerValue(String name) {
        AtomicLong timer = timers.get(name);
        return timer != null ? timer.get() : 0;
    }
    
    /**
     * 获取仪表盘指标值
     */
    public double getGaugeValue(String name) {
        return gauges.getOrDefault(name, 0.0);
    }
    
    /**
     * 获取所有指标
     */
    public Map<String, Object> getAllMetrics() {
        Map<String, Object> allMetrics = new ConcurrentHashMap<>();
        
        // 添加计数器
        Map<String, Long> counterValues = new ConcurrentHashMap<>();
        counters.forEach((name, counter) -> counterValues.put(name, counter.get()));
        allMetrics.put("counters", counterValues);
        
        // 添加计时器
        Map<String, Long> timerValues = new ConcurrentHashMap<>();
        timers.forEach((name, timer) -> timerValues.put(name, timer.get()));
        allMetrics.put("timers", timerValues);
        
        // 添加仪表盘指标
        allMetrics.put("gauges", new ConcurrentHashMap<>(gauges));
        
        return allMetrics;
    }
    
    /**
     * 重置所有指标
     */
    public void resetMetrics() {
        counters.clear();
        timers.clear();
        gauges.clear();
        log.info("Reset all metrics");
    }
    
    @Override
    public String getListenerName() {
        return LISTENER_NAME;
    }
    
    @Override
    public int getPriority() {
        return 10; // 较高优先级，确保指标及时收集
    }
    
    @Override
    public boolean supportsEventType(ProcessingEvent.EventType eventType) {
        return SUPPORTED_EVENTS.contains(eventType);
    }
    
    @Override
    public boolean isAsync() {
        return true; // 异步处理，避免影响主流程性能
    }
    
    @Override
    public ListenerType getListenerType() {
        return ListenerType.MONITORING;
    }
}